using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

public class OrderServiceTests
{
    [Test]
    public void AddOrder_NewOrder_ShouldAddSuccessfully()
    {
        OrderService orderService = new OrderService();
        Order newOrder = new Order { OrderId = 1, CustomerName = "Alice", TotalAmount = 100 };
        
        orderService.AddOrder(newOrder);
        
        Assert.AreEqual(1, orderService.FindOrders(o => o.OrderId == 1).Count);
    }

    [Test]
    public void AddOrder_ExistingOrderId_ShouldThrowException()
    {
        OrderService orderService = new OrderService();
        Order order1 = new Order { OrderId = 1, CustomerName = "Alice", TotalAmount = 100 };
        orderService.AddOrder(order1);
        
        Order order2 = new Order { OrderId = 1, CustomerName = "Bob", TotalAmount = 200 };
        
        Assert.Throws<Exception>(() => orderService.AddOrder(order2));
    }

    [Test]
    public void RemoveOrder_ExistingOrder_ShouldRemoveSuccessfully()
    {
        OrderService orderService = new OrderService();
        Order newOrder = new Order { OrderId = 1, CustomerName = "Alice", TotalAmount = 100 };
        orderService.AddOrder(newOrder);
        
        orderService.RemoveOrder(1);
        
        Assert.AreEqual(0, orderService.FindOrders(o => o.OrderId == 1).Count);
    }

    [Test]
    public void RemoveOrder_NonExistingOrder_ShouldThrowException()
    {
        OrderService orderService = new OrderService();
        
        Assert.Throws<Exception>(() => orderService.RemoveOrder(1));
    }

    [Test]
    public void UpdateOrder_ExistingOrder_ShouldUpdateSuccessfully()
    {
        OrderService orderService = new OrderService();
        Order newOrder = new Order { OrderId = 1, CustomerName = "Alice", TotalAmount = 100 };
        orderService.AddOrder(newOrder);
        
        Order updatedOrder = new Order { OrderId = 1, CustomerName = "Alice Smith", TotalAmount = 120 };
        orderService.UpdateOrder(updatedOrder);
        
        Order resultOrder = orderService.FindOrders(o => o.OrderId == 1).Single();
        Assert.AreEqual("Alice Smith", resultOrder.CustomerName);
        Assert.AreEqual(120, resultOrder.TotalAmount);
    }

    [Test]
    public void UpdateOrder_NonExistingOrder_ShouldThrowException()
    {
        OrderService orderService = new OrderService();
        Order newOrder = new Order { OrderId = 1, CustomerName = "Bob", TotalAmount = 200 };
        
        Assert.Throws<Exception>(() => orderService.UpdateOrder(newOrder));
    }

    [Test]
    public void FindOrders_MatchingCondition_ShouldReturnOrders()
    {
        OrderService orderService = new OrderService();
        orderService.AddOrder(new Order { OrderId = 1, CustomerName = "Alice", TotalAmount = 100 });
        orderService.AddOrder(new Order { OrderId = 2, CustomerName = "Bob", TotalAmount = 200 });
        
        List<Order> result = orderService.FindOrders(o => o.TotalAmount > 150);
        
        Assert.AreEqual(1, result.Count);
        Assert.AreEqual("Bob", result[0].CustomerName);
    }

    [Test]
    public void FindOrders_NonMatchingCondition_ShouldReturnEmptyList()
    {
        OrderService orderService = new OrderService();
        orderService.AddOrder(new Order { OrderId = 1, CustomerName = "Alice", TotalAmount = 100 });
        
        List<Order> result = orderService.FindOrders(o => o.TotalAmount > 150);
        
        Assert.AreEqual(0, result.Count);
    }

    [Test]
    public void OrderOrders_ByOrderId_ShouldReturnSortedList()
    {
        OrderService orderService = new OrderService();
        orderService.AddOrder(new Order { OrderId = 2, CustomerName = "Bob", TotalAmount = 200 });
        orderService.AddOrder(new Order { OrderId = 1, CustomerName = "Alice", TotalAmount = 100 });
        
        List<Order> result = orderService.OrderOrders(o => o.OrderId);
        
        Assert.AreEqual(1, result[0].OrderId);
        Assert.AreEqual(2, result[1].OrderId);
    }

    [Test]
    public void ExportAndImport_Orders_ShouldMatch()
    {
        OrderService orderService = new OrderService();
        orderService.AddOrder(new Order { OrderId = 1, CustomerName = "Alice", TotalAmount = 100 });
        orderService.AddOrder(new Order { OrderId = 2, CustomerName = "Bob", TotalAmount = 200 });
        
        string filePath = "test_orders.xml";
        orderService.Export(filePath);
        
        OrderService newOrderService = new OrderService();
        newOrderService.Import(filePath);
        
        List<Order> importedOrders = newOrderService.FindOrders(o => true);
        
        Assert.AreEqual(2, importedOrders.Count);
        Assert.AreEqual("Alice", importedOrders[0].CustomerName);
        Assert.AreEqual("Bob", importedOrders[1].CustomerName);
        
        File.Delete(filePath);
    }
}